package top.codedance.iotp.tools.terminal.comer.listenner;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.common.util.BytesBuilder;
import top.codedance.iotp.common.util.HexUtil;
import top.codedance.iotp.tools.terminal.TerminalApplication;
import top.codedance.iotp.tools.terminal.comer.ComClient;
import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;

import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;

public class SerialPortListener implements SerialPortDataListener {
    private ComClient cc;
    private BytesBuilder gbb = new BytesBuilder();
    private long lastUpdateTime = 0;

    public SerialPortListener(ComClient cc) {
        this.cc = cc;

        clean();
    }

    @Override
    public int getListeningEvents() {
        return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
    }

    @Override
    public synchronized void serialEvent(SerialPortEvent serialPortEvent) {
        BytesBuilder bb = new BytesBuilder();
        SerialPort serialPort = serialPortEvent.getSerialPort();
        int avai = serialPort.bytesAvailable();
        while (avai > 0) {
            byte[] data = new byte[avai];
            serialPort.readBytes(data, avai);
            bb.append(data);
            avai = serialPort.bytesAvailable();
        }
        byte[] bytes = bb.toArray();
        try {
            synchronized (this){
                gbb.append(bytes);
                JSONObject result = JSON.parseObject(new String(gbb.toArray(), StandardCharsets.UTF_8));
                if (result.getBoolean("ok")) {
                    result = reductionData(result);
                    cc.appendResult(result.getString("context"));
                } else {
                    cc.appendError(result.toJSONString());
                }
            }
        } catch (Exception ex) {
            cc.appendResult(HexUtil.bytesToHexFun1(gbb.toArray()));
        } finally {
            gbb = new BytesBuilder();
            lastUpdateTime = System.currentTimeMillis();
        }
    }

    private void clean() {
        new Thread(() -> {
            while (true) {
                try {
                    if (System.currentTimeMillis() - lastUpdateTime > 1000 * 5) {
                        synchronized (this) {
                            if (gbb.length() > 0) {
                                cc.appendResult(new String(gbb.toArray()));
                                gbb = new BytesBuilder();
                                lastUpdateTime = System.currentTimeMillis();
                            }
                        }
                    }
                    Thread.sleep(100);
                } catch (Exception e) {
                    TerminalApplication.syslogInfo(e.getMessage());
                }
            }
        }).start();
    }

    /**
     * 还原结果
     * @param data
     * @return
     */
    private JSONObject reductionData(JSONObject data){
        try {
            if (data.containsKey("hex")) {
                String hex = data.getString("hex");
                String[] hexs = hex.split("\\.");
                for (int i = 0; i < hexs.length; i++) {
                    if (i == hexs.length - 1) {
                        data.put(hexs[i], new String(DatatypeConverter.parseHexBinary(data.getString(hexs[i]))));
                    } else {
                        data = data.getJSONObject(hexs[i]);
                    }
                }
            }
        } catch (Exception e) {
        } finally {
            return data;
        }
    }
}
